home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / sbin / update-initramfs < prev    next >
Text File  |  2008-06-24  |  10KB  |  548 lines

  1. #!/bin/sh
  2.  
  3. STATEDIR=/var/lib/initramfs-tools
  4. BOOTDIR=/boot
  5. CONF=/etc/initramfs-tools/update-initramfs.conf
  6. KPKGCONF=/etc/kernel-img.conf
  7. USETRIGGERS=true
  8. mode=""
  9. version=""
  10.  
  11. set -e
  12.  
  13. [ -r ${CONF} ] && . ${CONF}
  14.  
  15. if       $USETRIGGERS                        \
  16.     && [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ]        \
  17.     && [ $# = 1 ]                         \
  18.     && [ x"$1" = x-u ]                    \
  19.     && dpkg-trigger --check-supported 2>/dev/null
  20. then
  21.     if dpkg-trigger --no-await update-initramfs; then
  22.         echo "update-initramfs: deferring update (trigger activated)"
  23.         exit 0
  24.     fi
  25. fi
  26.  
  27. usage()
  28. {
  29.     if [ -n "${1}" ]; then
  30.         printf "${@}\n\n" >&2
  31.     fi
  32.     cat >&2 << EOF
  33. Usage: ${0} [OPTION]...
  34.  
  35. Options:
  36.  -k [version]    Specify kernel version or 'all'
  37.  -c        Create a new initramfs
  38.  -u        Update an existing initramfs
  39.  -d        Remove an existing initramfs
  40.  -t        Take over a custom initramfs with this one
  41.  -b        Set alternate boot directory
  42.  -v        Be verbose
  43.  -h        This message
  44.  
  45. EOF
  46.     exit 1
  47. }
  48.  
  49. # chroot check
  50. chrooted()
  51. {
  52.         # borrowed from udev's postinst
  53.         if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
  54.                 # the devicenumber/inode pair of / is the same as that of
  55.                 # /sbin/init's root, so we're *not* in a chroot and hence
  56.                 # return false.
  57.                 return 1
  58.         fi
  59.         return 0
  60. }
  61.  
  62. mild_panic()
  63. {
  64.     if [ -n "${1}" ]; then
  65.         printf "${@}\n" >&2
  66.     fi
  67.     exit 0
  68. }
  69.  
  70. panic()
  71. {
  72.     if [ -n "${1}" ]; then
  73.         printf "${@}\n" >&2
  74.     fi
  75.     exit 1
  76. }
  77.  
  78. verbose()
  79. {
  80.     if [ "${verbose}" = 1 ]; then
  81.         printf "${@}\n"
  82.     fi
  83. }
  84.  
  85. version_exists()
  86. {
  87.     [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
  88.     return $?
  89. }
  90.  
  91. set_initramfs()
  92. {
  93.     initramfs="${BOOTDIR}/initrd.img-${version}"
  94. }
  95.  
  96.  
  97. # backup initramfs while running
  98. backup_initramfs()
  99. {
  100.     [ ! -r "${initramfs}" ] && return 0
  101.     initramfs_bak="${initramfs}.dpkg-bak"
  102.     [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
  103.     ln -f "${initramfs}" "${initramfs_bak}" \
  104.         || cp -a "${initramfs}" "${initramfs_bak}"
  105.     verbose "Keeping ${initramfs_bak}"
  106. }
  107.  
  108. # keep booted initramfs
  109. backup_booted_initramfs()
  110. {
  111.     initramfs_bak="${initramfs}.dpkg-bak"
  112.  
  113.     # first time run thus no backup
  114.     [ ! -r "${initramfs_bak}" ] && return 0
  115.  
  116.     # chroot with no /proc
  117.     [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
  118.  
  119.     # no kept backup wanted
  120.     [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
  121.  
  122.     # no backup yet
  123.     if [ ! -r "${initramfs}.bak" ]; then
  124.         mv -f ${initramfs_bak} "${initramfs}.bak"
  125.         verbose "Backup ${initramfs}.bak"
  126.         return 0
  127.     fi
  128.  
  129.     # keep booted initramfs
  130.     uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
  131.     if [ -n "$uptime_days" ]; then
  132.         boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
  133.     fi
  134.     if [ -n "${boot_initramfs}" ]; then
  135.         mv -f "${initramfs_bak}" "${initramfs}.bak"
  136.         verbose "Backup ${initramfs}.bak"
  137.         return 0
  138.     fi
  139.     verbose "Removing current backup ${initramfs_bak}"
  140.     rm -f ${initramfs_bak}
  141. }
  142.  
  143. # nuke generated copy
  144. remove_initramfs()
  145. {
  146.     [ -z "${initramfs_bak}" ] && return 0
  147.     rm -f "${initramfs_bak}"
  148.     verbose "Removing ${initramfs_bak}"
  149. }
  150.  
  151.  
  152. generate_initramfs()
  153. {
  154.     echo "update-initramfs: Generating ${initramfs}"
  155.     OPTS="-o"
  156.     if [ "${verbose}" = 1 ]; then
  157.         OPTS="-v ${OPTS}"
  158.     fi
  159.     if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
  160.         mv -f "${initramfs}.new" "${initramfs}"
  161.         set_sha1
  162.     else
  163.         mkinitramfs_return="$?"
  164.         remove_initramfs
  165.         rm -f "${initramfs}.new"
  166.         if [ "$mkinitramfs_return" = "2" ]; then
  167.             # minversion wasn't met, exit 0
  168.             exit 0
  169.         fi
  170.         echo "update-initramfs: failed for ${initramfs}"
  171.         exit $mkinitramfs_return
  172.     fi
  173. }
  174.  
  175. # lilo call
  176. run_lilo()
  177. {
  178.     # show lilo errors on failure
  179.     if ! lilo -t  > /dev/null 2>&1 ; then
  180.         echo "ERROR lilo fails for new ${initramfs}:"
  181.         echo
  182.         lilo -t
  183.     fi
  184.     lilo
  185. }
  186.  
  187. # check if lilo is on mbr
  188. mbr_check()
  189. {
  190.     # try to discover grub and be happy
  191.     [ -r /boot/grub/menu.lst ] \
  192.         && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
  193.             /boot/grub/menu.lst)
  194.     [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
  195.         && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
  196.     [ -n "${dev}" ] && [ -r ${dev} ] \
  197.         && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
  198.         | grep -q GRUB && return 0
  199.  
  200.     # check out lilo.conf for validity
  201.     boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
  202.     [ -z "${boot}" ] && return 0
  203.     case ${boot} in
  204.     /dev/md/*)
  205.         if [ -r /proc/mdstat ]; then
  206.             MD=${boot#/dev/md/}
  207.             boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
  208.             /proc/mdstat)"
  209.         fi
  210.         ;;
  211.     /dev/md*)
  212.         if [ -r /proc/mdstat ]; then
  213.             MD=${boot#/dev/}
  214.             boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
  215.             /proc/mdstat)"
  216.         fi
  217.         ;;
  218.     esac
  219.     [ ! -r "${boot}" ] && return 0
  220.     dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
  221.         && run_lilo && return 0
  222.  
  223.     # no idea which bootloader is used
  224.     echo
  225.     echo "WARNING: grub and lilo installed."
  226.     echo "If you use grub as bootloader everything is fine."
  227.     echo "If you use lilo as bootloader you must run lilo!"
  228.     echo
  229. }
  230.  
  231. # Invoke bootloader
  232. run_bootloader()
  233. {
  234.     # if both lilo and grub around, figure out if lilo needs to be run
  235.     if [ -x /sbin/grub ] || [ -e /boot/grub/menu.lst ] \
  236.     || [ -x /usr/sbin/grub ]; then
  237.         if [ -e /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  238.             [ -r "${KPKGCONF}" ] && \
  239.             do_b=$(awk  '/^do_bootloader/{print $3}' "${KPKGCONF}")
  240.             if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
  241.                 || [ "${do_b}" = "YES" ]; then
  242.                 run_lilo
  243.                 return 0
  244.             elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
  245.                 || [ "${do_b}" = "NO" ]; then
  246.                 return 0
  247.             else
  248.                 mbr_check
  249.                 return 0
  250.             fi
  251.         fi
  252.         return 0
  253.     fi
  254.     if [ -r /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  255.         run_lilo
  256.         return 0
  257.     fi
  258.     if [ -x /sbin/elilo ]; then
  259.         elilo
  260.         return 0
  261.     fi
  262.     if [ -r /etc/zipl.conf ]; then
  263.         zipl
  264.     fi
  265. }
  266.  
  267. compare_sha1()
  268. {
  269.     sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
  270.     return $?
  271. }
  272.  
  273. # Note that this must overwrite so that updates work.
  274. set_sha1()
  275. {
  276.     sha1sum "${initramfs}" > "${STATEDIR}/${version}"
  277. }
  278.  
  279. delete_sha1()
  280. {
  281.     rm -f "${STATEDIR}/${version}"
  282. }
  283.  
  284. # ro /boot is not modified
  285. ro_boot_check()
  286. {
  287.     # check irrelevant inside of a chroot
  288.     if [ ! -r /proc/mounts ] || chrooted; then
  289.         return 0
  290.     fi
  291.  
  292.     boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
  293.         && $2 == "/boot") print "ro"}' /proc/mounts)
  294.     if [ -n "${boot_opts}" ]; then
  295.         echo "WARNING: /boot is ro mounted."
  296.         echo "update-initramfs: Not updating ${initramfs}"
  297.         exit 0
  298.     fi
  299. }
  300.  
  301. get_sorted_versions()
  302. {
  303.     version_list=""
  304.  
  305.     for gsv_x in "${STATEDIR}"/*; do
  306.         gsv_x="$(basename "${gsv_x}")"
  307.         if [ "${gsv_x}" = '*' ]; then
  308.             return 0
  309.         fi
  310.         worklist=""
  311.         for gsv_i in $version_list; do
  312.             if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
  313.                 worklist="${worklist} ${gsv_x} ${gsv_i}"
  314.                 gsv_x=""
  315.             else
  316.                 worklist="${worklist} ${gsv_i}"
  317.             fi
  318.         done
  319.         if [ "${gsv_x}" != "" ]; then
  320.             worklist="${worklist} ${gsv_x}"
  321.         fi
  322.         version_list="${worklist}"
  323.     done
  324.  
  325.     verbose "Available versions: ${version_list}"
  326. }
  327.  
  328. set_current_version()
  329. {
  330.     if [ -f /boot/initrd.img-`uname -r` ]; then
  331.         version=`uname -r`
  332.     fi
  333. }
  334.  
  335. set_linked_version()
  336. {
  337.     if [ -L /initrd.img ]; then
  338.         linktarget="$(basename "$(readlink /initrd.img)")"
  339.     fi
  340.  
  341.     if [ -L /boot/initrd.img ]; then
  342.         linktarget="$(basename "$(readlink /boot/initrd.img)")"
  343.     fi
  344.  
  345.     if [ -z "${linktarget}" ]; then
  346.         return
  347.     fi
  348.  
  349.     version="${linktarget##initrd.img-}"
  350. }
  351.  
  352. set_highest_version()
  353. {
  354.     get_sorted_versions
  355.     set -- ${version_list}
  356.     version=${1}
  357. }
  358.  
  359. create()
  360. {
  361.     if [ -z "${version}" ]; then
  362.         usage "Create mode requires a version argument"
  363.     fi
  364.  
  365.     set_initramfs
  366.  
  367.     if [ "${takeover}" = 0 ]; then
  368.         if version_exists "${version}"; then
  369.             panic "Cannot create version ${version}: already exists"
  370.         fi
  371.  
  372.         if [ -e "${initramfs}" ]; then
  373.             panic "${initramfs} already exists, cannot create."
  374.         fi
  375.     fi
  376.  
  377.     generate_initramfs
  378. }
  379.  
  380. update()
  381. {
  382.     if [ "${update_initramfs}" = "no" ]; then
  383.         echo "update-initramfs: Not updating initramfs."
  384.         exit 0
  385.     fi
  386.  
  387.     if [ -z "${version}" ]; then
  388.         set_linked_version
  389.     fi
  390.  
  391.     if [ -z "${version}" ]; then
  392.         set_highest_version
  393.     fi
  394.  
  395.     if [ -z "${version}" ]; then
  396.         set_current_version
  397.     fi
  398.  
  399.     if [ -z "${version}" ]; then
  400.         verbose "Nothing to do, exiting."
  401.         exit 0
  402.     fi
  403.  
  404.     set_initramfs
  405.  
  406.     ro_boot_check
  407.  
  408.     altered_check
  409.  
  410.     backup_initramfs
  411.  
  412.     generate_initramfs
  413.  
  414.     run_bootloader
  415.  
  416.     backup_booted_initramfs
  417. }
  418.  
  419. delete()
  420. {
  421.     if [ -z "${version}" ]; then
  422.         usage "Delete mode requires a version argument"
  423.     fi
  424.  
  425.     set_initramfs
  426.  
  427.     if [ ! -e "${initramfs}" ]; then
  428.         panic "Cannot delete ${initramfs}, doesn't exist."
  429.     fi
  430.  
  431.     if ! version_exists "${version}"; then
  432.         panic "Cannot delete version ${version}: Not created by this utility."
  433.     fi
  434.  
  435.     altered_check
  436.  
  437.     echo "update-initramfs: Deleting ${initramfs}"
  438.  
  439.     delete_sha1
  440.  
  441.     rm -f "${initramfs}"
  442. }
  443.  
  444. # Check for update mode on existing and modified initramfs
  445. altered_check()
  446. {
  447.     # No check on takeover
  448.     [ "${takeover}" = 1 ] && return 0
  449.     if [ ! -e "${initramfs}" ]; then
  450.         mild_panic "${initramfs} does not exist. Cannot update."
  451.     fi
  452.     if ! compare_sha1; then
  453.         echo "update-initramfs: ${initramfs} has been altered." >&2
  454.         mild_panic "update-initramfs: Cannot update. Override with -t option."
  455.     fi
  456. }
  457.  
  458. # Defaults
  459. verbose=0
  460. yes=0
  461. # We default to takeover=1 in Ubuntu, but not Debian
  462. takeover=1
  463.  
  464. ##
  465.  
  466. while getopts "k:cudyvtb:h?" flag; do
  467.     case "${flag}" in
  468.     k)
  469.         version="${OPTARG}"
  470.         ;;
  471.     c)
  472.         mode="c"
  473.         ;;
  474.     d)
  475.         mode="d"
  476.         ;;
  477.     u)
  478.         mode="u"
  479.         ;;
  480.     v)
  481.         verbose="1"
  482.         ;;
  483.     y)
  484.         yes="1"
  485.         ;;
  486.     t)
  487.         takeover="1"
  488.         ;;
  489.     b)
  490.         BOOTDIR="${OPTARG}"
  491.         if [ ! -d "${BOOTDIR}" ]; then
  492.             echo "Error: ${BOOTDIR} is not a directory."
  493.             exit 1
  494.         fi
  495.         ;;
  496.     h|?)
  497.         usage
  498.         ;;
  499.     esac
  500. done
  501.  
  502. # Validate arguments
  503. if [ -z "${mode}" ]; then
  504.     usage "You must specify at least one of -c, -u, or -d."
  505. fi
  506.  
  507. if [ "${version}" = "all" ] \
  508.     || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
  509.     : FIXME check for --yes, and if not ask are you sure
  510.     get_sorted_versions
  511.     if [ -z "${version_list}" ]; then
  512.         verbose "Nothing to do, exiting."
  513.         exit 0
  514.     fi
  515.  
  516.     OPTS="-b ${BOOTDIR}"
  517.     if [ "${verbose}" = "1" ]; then
  518.         OPTS="${OPTS} -v"
  519.     fi
  520.     if [ "${takeover}" = "1" ]; then
  521.         OPTS="${OPTS} -t"
  522.     fi
  523.     if [ "${yes}" = "1" ]; then
  524.         OPTS="${OPTS} -y"
  525.     fi
  526.     for u_version in ${version_list}; do
  527.         # Don't stop if one version doesn't work.
  528.         set +e
  529.         verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
  530.         "${0}" -${mode} -k "${u_version}" ${OPTS}
  531.         set -e
  532.     done
  533.     exit 0
  534. fi
  535.  
  536.  
  537. case "${mode}" in
  538.     c)
  539.         create
  540.         ;;
  541.     d)
  542.         delete
  543.         ;;
  544.     u)
  545.         update
  546.         ;;
  547. esac
  548.